package com.lanchetech.admin.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.admin.service.BlogService;
import com.lanchetech.bean.request.BlogPageReq;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.request.TagCategoryPageReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.BlogDetailVO;
import com.lanchetech.bean.vo.BlogVO;
import com.lanchetech.bean.vo.StatisticsCountVO;
import com.lanchetech.bean.vo.TagSpuStatisticsVO;
import com.lanchetech.common.enums.BlogAuditStatusEnum;
import com.lanchetech.common.enums.DeletedEnum;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.common.enums.UserTagTypeEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.DaoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    BlogMapper blogMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    TagCategoryMapper tagCategoryMapper;

    @Autowired
    BlogSpuMapper blogSpuMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    BlogCollectMapper blogCollectMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    CommonCommentMapper commonCommentMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public BaseResp auditBlog(Long id, Byte auditStatus, String remark) {
        Blog blog = blogMapper.selectByPrimaryKey(id);
        blogMapper.updateAuditStatusAndRemarkAndUpdatedAtById(auditStatus, remark, new Date(), id);

        if (blog.getFirstTagId() != null && blog.getFirstTagId() != 0 && BlogAuditStatusEnum.PASS.getAuditStatus().equals(auditStatus)) {
            //审核通过就更新统计数据
            saveEditStatistics(null, blog.getFirstTagId());
        }

        return new BaseResp();
    }

    private void saveEditStatistics(Blog blog, Long firstTagId) {
        ValueOperations<String, List<TagSpuStatisticsVO>> operations = redisTemplate.opsForValue();
        if (blog == null || blog.getTitle() != null) {

            //标题总字数
            StatisticsCountVO totalWordCounts = blogMapper.getTotalWordCountByFirstTagId(firstTagId);

            //博文总数
            StatisticsCountVO itemCount = blogMapper.getItemCountByFirstTagId(firstTagId);

            TagSpuStatisticsVO vo = new TagSpuStatisticsVO();
            vo.setType(UserTagTypeEnum.BLOG.getType());
            vo.setRelateId(firstTagId);
            vo.setItemCount(itemCount.getCount());
            vo.setUpdateAt(new Date());
            vo.setTotalWordCount(totalWordCounts.getCount());

            if (operations.get("tfidf" + UserTagTypeEnum.BLOG.getType()) != null) {
                //更新其中一条
                List<TagSpuStatisticsVO> statisticsVO = operations.get("tfidf" + UserTagTypeEnum.BLOG.getType());
                List<TagSpuStatisticsVO> addStatistics = new ArrayList<>();
                statisticsVO.stream().forEach(item -> {
                    if (item.getRelateId().equals(firstTagId)) {
                        BeanUtils.copyProperties(vo, item);
                    } else {
                        addStatistics.add(vo);
                    }
                });
                if (!CollectionUtils.isEmpty(addStatistics)) {
                    statisticsVO.addAll(addStatistics);
                }
                operations.set("tfidf" + UserTagTypeEnum.BLOG.getType(), statisticsVO);
            }
        }
    }

    @Override
    public ResultData<BasePageResp<BlogVO>> getBlogPage(BlogPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BlogVO> list = blogMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(BlogVO::getUserId).collect(Collectors.toList()));
            List<Long> tagCategoryIds = list.stream().map(BlogVO::getFirstTagId).collect(Collectors.toList());
            tagCategoryIds.addAll(list.stream().map(BlogVO::getSecondTagId).collect(Collectors.toList()));
            Map<Long, TagCategory> categoryMap = daoService.getTagCategoryMap(tagCategoryIds);

            List<BlogSpu> blogSpus = blogSpuMapper.findByBlogIds(list.stream().map(BlogVO::getId).collect(Collectors.toList()));
            List<Long> spuIds = blogSpus.stream().map(BlogSpu::getSpuId).collect(Collectors.toList());
            Map<Long, List<Spu>> blogSpuMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(spuIds)) {
                Map<Long, Spu> spuMap = daoService.getSpuMap(spuIds);
                if (!CollectionUtils.isEmpty(blogSpus)) {
                    blogSpus.stream().forEach(item -> {
                        if (!blogSpuMap.containsKey(item.getBlogId())) {
                            List<Spu> spuList = new ArrayList<>();
                            spuList.add(spuMap.get(item.getSpuId()));
                            blogSpuMap.put(item.getBlogId(), spuList);
                        } else {
                            List<Spu> spuList = blogSpuMap.get(item.getBlogId());
                            spuList.add(spuMap.get(item.getSpuId()));
                            blogSpuMap.put(item.getBlogId(), spuList);
                        }
                    });
                }
            }

            list.stream().forEach(item -> {
                item.setNickname(userMap.get(item.getUserId()).getNickname());
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setFirstTagTitle(categoryMap.get(item.getFirstTagId()) != null ? categoryMap.get(item.getFirstTagId()).getTitle() : null);
                item.setSecondTagTitle(categoryMap.get(item.getSecondTagId()) != null ? categoryMap.get(item.getSecondTagId()).getTitle() : null);
                item.setSpuList(blogSpuMap.get(item.getId()));
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp auditTagCategory(TagCategory req) {
        if (req.getId() == null) {
            req.setDeleted(DeletedEnum.DEFAULT.getStatus());
            req.setCreatedAt(new Date());
            req.setUpdatedAt(new Date());
            tagCategoryMapper.insert(req);
        } else {
            req.setDeleted(DeletedEnum.DEFAULT.getStatus());
            req.setUpdatedAt(new Date());
            tagCategoryMapper.updateByPrimaryKeySelective(req);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<TagCategory>> getTagCategoryPage(TagCategoryPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<TagCategory> list = tagCategoryMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp deleteTagCategory(Long id) {
        tagCategoryMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);
        return new BaseResp();
    }

    @Override
    public ResultData<TagCategory> getTagCategoryDetail(Long id) {
        TagCategory tagCategory = tagCategoryMapper.selectByPrimaryKey(id);
        return new ResultData<>(tagCategory);
    }

    @Override
    public ResultData<List<TagCategory>> getTagCategoryList(TagCategory req) {
        List<TagCategory> list = tagCategoryMapper.findAllList(req);
        return new ResultData<>(list);
    }

    @Override
    public ResultData<BlogDetailVO> getBlogDetail(Long id) {
        BlogDetailVO vo = new BlogDetailVO();
        Blog blog = blogMapper.selectByPrimaryKey(id);
        TagCategory firstTag = tagCategoryMapper.selectByPrimaryKey(blog.getFirstTagId());
        TagCategory secondTag = tagCategoryMapper.selectByPrimaryKey(blog.getSecondTagId());
        BeanUtils.copyProperties(blog, vo);
        User blogUser = userMapper.selectByPrimaryKey(blog.getUserId());
        vo.setNickname(blogUser.getNickname());
        vo.setAvatar(blogUser.getAvatar());
        List<BlogSpu> blogSpus = blogSpuMapper.findAllByBlogId(id);
        List<Long> spuIds = blogSpus.stream().map(BlogSpu::getSpuId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(spuIds)) {
            vo.setSpuList(spuMapper.findAllByIds(spuIds));
        }
        vo.setFirstTagTitle(firstTag != null ? firstTag.getTitle() : null);
        vo.setSecondTagTitle(secondTag != null ? secondTag.getTitle() : null);
        vo.setCollectNum(blogCollectMapper.countByBlogId(id));
        vo.setCommentNum(commonCommentMapper.countByRelateId(id));
        return new ResultData<>(vo);
    }
}
